iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

JS 加強筆記系列 第 23

Day 23:promise 實作 (1)

  • 分享至 

  • xImage
  •  

今天這篇開始參考這本書,看看簡單的 promise 實作 (希望看得懂),從另一個角度來理解 promise。

這個實作叫做 DemoPromise,是一個有三個原型方法的 class:

DemoPromise.prototype.resolve(value)
DemoPromise.prototype.reject(reason)
DemoPromise.prototype.then(onFulfilled, onRejected)

也就是說這裡把 resolvereject 當作方法,而不是像真的 promise 一樣是建構式的 callback 函式。

基本功能

初步讓 DemoPromise 可以有一些基本功能:

  • 可以建立 promise。
  • 可以 resolve 或 reject promise,而且只能執行一次。
  • 可以藉由 then 來設定待執行的 callback (這個階段還不能鏈接)。

以程式碼來說,就是可以做到這樣:

const dp = new DemoPromise();
dp.resolve('abc');
dp.then(function (value) {
    console.log(value); // abc
});

then

then 有兩種情況:

  • 如果 promise 狀態是 'pending',那就把呼叫 onFulfilledonRejected 排進工作 (fulfillReactions) 中,等待有結果時執行。
  • 如果 promise 已經是 'resolved' 或 'rejected',則可以立即呼叫 onFulfilledonRejected
then(onFulfilled, onRejected) {
    const self = this;
    const fulfilledTask = function () {
        onFulfilled(self.promiseResult);
    };
    const rejectedTask = function () {
        onRejected(self.promiseResult);
    };
    switch (this.promiseState) {
        case 'pending':
            this.fulfillReactions.push(fulfilledTask);
            this.rejectReactions.push(rejectedTask);
            break;
        case 'fulfilled':
            addToTaskQueue(fulfilledTask);
            break;
        case 'rejected':
            addToTaskQueue(rejectedTask);
            break;
    }
}

function addToTaskQueue(task) {
    setTimeout(task, 0);
}

resolve

resolve 做的事情是:如果 promise 已經 settled,則不做任何事 (因為只能 settle 一次),否則將 promise 狀態改成 'fulfilled',並將結果存進 promise 的結果屬性裡。接著執行已經排好的成功處理 (fulfillReactions)。

resolve(value) {
    if (this.promiseState !== 'pending') return;
    this.promiseState = 'fulfilled';
    this.promiseResult = value;
    this._clearAndEnqueueReactions(this.fulfillReactions);
    return this; // 這樣讓後面可以鏈接
}
_clearAndEnqueueReactions(reactions) {
    this.fulfillReactions = undefined;
    this.rejectReactions = undefined;
    reactions.map(addToTaskQueue);
}

reject 是同樣的邏輯,只是改成失敗的狀態。


上一篇
Day 22:async/ await (2)
下一篇
Day 24:promise 實作 (2)
系列文
JS 加強筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言